package com.example.demo.controller;

import com.example.demo.model.User;
import com.sun.xml.internal.ws.api.message.Header;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description:
 */
@Controller
@ResponseBody
// 在类上加 @RequestMapping，表示这是一级地址，可以省略
// 此时在方法中再加 @RequestMapping，方法的 url 就是二级地址
@RequestMapping("/user")
@Slf4j
public class UserController {

    @RequestMapping("/login2")
    public Map<String, Object> login2(@RequestBody User user) {
        String username = user.getUsername();
        String password = user.getPassword();
        HashMap<String, Object> result = new HashMap<>();
        int state = 200;
        int data = -1; // 等于1，表示登录成功，否则，登录失败
        // 错误信息
        String msg = "未知错误";
        if(StringUtils.hasLength(username) && StringUtils.hasLength(password)) {
            if(username.equals("admin") && password.equals("admin")) {
                data = 1;
                msg = "";
            }else {
                msg = "用户名或密码错误";
            }
        }else {
            // 参数为空的情况
            msg = "参数异常";
        }
        result.put("state", state);
        result.put("data", data);
        result.put("msg", msg);
        return result;
    }

    // 从配置文件中读取图片的保存路径
    @Value("${img.path}")
    private String imgPath;

    @RequestMapping("/sayhi")
    // 表示此时返回的结果是页面内容，而不是某个静态页面
    // 如果把注解放到类上面，就表示类中的所有方法都是返回页面内容
    @ResponseBody
    public String sayHi() {
        return "Hello World!" + imgPath;
    }

    // 表示该方法只支持post请求，而不支持其他请求
    @RequestMapping(method = RequestMethod.POST, value = "/sayhi2")
    public String sayHi2() {
        return "你好，世界!";
    }

    // 标明只支持某种请求的方法，是比上述使用 RequestMapping 更优化的方法
    @PostMapping("/sayhi3")
    public String sayHi3() {
        return "Hello World!";
    }

    @RequestMapping("/getuser")
    // 参数使用引用类型，如果前端没有带上id，那么使用基本类型就会报错
    // 客户端发来的请求 key 必须和这里的参数名相同，否则就获取不到这个 key 的 value 值
    public User getUserById(Integer id) {
        User user = new User();
        user.setId(id == null ? 0 : id);
        user.setUsername("zhangsan");
        return user;
    }

    // 多个参数获取
    // 如果看不惯前端的参数名，可以重命名，使用 @RequestParam，但需要注意的是：
    //    在这个注释中，有一个参数 required，默认是 true，表示前端必须给我们传递这个名字的参数
    //    如果不传，就会直接报错，因此我们使用时，需要把参数设为false
    @RequestMapping("/login")
    public boolean login(@RequestParam(value = "name", required = false) String username, String password) {
        if(username == null || password == null) {
            return false;
        }
        if(!username.equals("zhangsan") || !password.equals("123")) {
            return false;
        }
        return true;
    }

    // 获取一个对象，可以解决参数过多不方便也不美观的情况
    // spring MVC会将从前端获取到的数据的key与User的属性一一对应进行赋值并传参
    @RequestMapping("/reg")
    public String reg(User user) {
        return "用户信息: " + user;
    }

    // 接收客户端的 json 数据
    // 通过 @RequestBody 获取
    @RequestMapping("/reg2")
    public String reg2(@RequestBody User user) {
        return "用户信息: " + user;
    }

    // 获取 url 中的参数
    // 将参数伪装成 url 地址，在搜索引擎进行搜索时，地址匹配的优先级是高于参数匹配的
    // 因为地址不常变，但参数经常变，这种做法可以让我们把想给用户展示的页面放前面
    // 对点击量和公司的盈利发展都是有好处的
    // 具体实现通过 @PathVariable 完成
    @RequestMapping("/reg3/{username}/{password}")
    public String reg3(@PathVariable String username, @PathVariable String password) {
        return username + " " + password;
    }

    // 接收文件操作
    // 在参数前加上 @RequestPart("文件名")，其中文件名表示 key 的名字
    // 参数类型是 MultipartFile
    @RequestMapping("/upfile")
    public boolean upFile(@RequestPart("img")MultipartFile file) {
        boolean result = false;
        // 1. 目录=imgpath
        //    生产环境比如 linux 没有C盘/D盘，因此需要把目录的地址放到配置文件
        //    后期运维也能通过修改配置文件来改变保存地址
        // 2. 保存的图片名称(图片名不能重复)，使用【UUID】，保证图片名称不会重复
        // 3. 获取原上传文件的格式，先获取文件名称，再通过substring配合"."的位置的方式切割
        String fileName = file.getOriginalFilename();
        fileName = fileName.substring(fileName.lastIndexOf("."));
        fileName = UUID.randomUUID().toString() + fileName;

        // 将文件复制到本地目录，需要创建一个文件类型的对象
        try {
            file.transferTo(new File(imgPath + fileName));
            result = true;
        } catch (IOException e) {
            // 打印一个日志，先在类上标明 @Slf4j 注释
            log.error("上传文件失败！失败原因是：" + e.getMessage());

        }
        return result;
    }

    // 获取 Cookie/Session/header
    @RequestMapping("/getcookie")
    public String getCookie(HttpServletRequest request) {
        //获取 Cookie
        Cookie[] cookies = request.getCookies();
        StringBuilder stringBuilder = new StringBuilder();
        if(cookies != null) {
            for(Cookie cookie: cookies) {
                stringBuilder.append("| cookieName: " + cookie.getName() +
                        " | cookieValue: " + cookie.getValue());
            }
        }
        return stringBuilder.toString();
    }

    // 更简单的获取 Cookie，通过 Spring MVC
    @RequestMapping("/getcookie2")
    public String getCookie2(@CookieValue("test") String cookie) {
        return cookie;
    }

    // 获取 header 对象方法一
    @RequestMapping("/getheader")
    public String getHeader(HttpServletRequest request) {
        return "header: " + request.getHeader("User-Agent");
    }

    // 获取 header 对象方法二
    @RequestMapping("/getheader2")
    public String getHeader2(@RequestHeader("User-Agent") String userAgent) {
        return "header: " + userAgent;
    }

    // 设置 Session，只有这种方法
    @RequestMapping("/setsession")
    public boolean setSession(HttpServletRequest request) {
        boolean result = false;
        // 1. 得到HttpSession对象，如果没有Session，就创建
        HttpSession session = request.getSession(true);
        // 2. 使用 setAttribute 设置
        session.setAttribute("userinfo", "zhangsan");
        result = true;
        return result;
    }

    // 获取 Session 方法一，使用HttpServletRequest
    @RequestMapping("/getsession")
    public String getSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if(session == null) {
            return "null";
        }
        return session.toString();
    }

    // 获取 Session 方法二，使用注释
    @RequestMapping("/getsession2")
    public String getSession2(@SessionAttribute(value = "userinfo", required = false) String userInfo) {
        return userInfo;
    }

}
